package com.atguigu.tingshu.common.annotation;

import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.result.ResultCodeEnum;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.model.user.UserInfo;
import jakarta.servlet.http.HttpServletRequest;
import lombok.SneakyThrows;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.net.Authenticator;

//这是切面类   切面类上写具体的登录校验逻辑
@Aspect
@Component
public class GuiGuLoginAspect {

    @Autowired
    private RedisTemplate redisTemplate;
    //环绕通知
    @SneakyThrows
    //环绕通知用在哪个类哪个方法里                       哪个方法上边有GuiGuLogin注解 ，就使用环绕通知
    @Around("execution(* com.atguigu.tingshu.*.api.*.*(..)) && @annotation(guiGuLogin)")
    public Object login(ProceedingJoinPoint joinPoint, GuiGuLogin guiGuLogin){
        //joinPoint就表示切入点的信息
        //1 从请求头中获取token
        //获取request对象
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();

        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) requestAttributes;
        HttpServletRequest request = servletRequestAttributes.getRequest();
        String token = request.getHeader("token");
        //判断是否必须要进行登录校验
        if(guiGuLogin.required()){
            if(StringUtils.isEmpty(token)){
                //表示没有登录
                throw new GuiguException(ResultCodeEnum.LOGIN_AUTH);
            }
            //2 根据token去查询redis
            UserInfo userInfo = (UserInfo) redisTemplate.opsForValue().get(token);
            if(userInfo==null){
                //表示没有登录
                throw new GuiguException(ResultCodeEnum.LOGIN_AUTH);
            }
        }
        //获取redis中的userId，放到ThreadLocal里面去
        if(!StringUtils.isEmpty(token)){
            UserInfo userInfo = (UserInfo) redisTemplate.opsForValue().get(token);
            if(userInfo!=null){
                //表示登录
                Long userId = userInfo.getId();
                AuthContextHolder.setUserId(userId);
            }
        }

        //记得放行
        Object proceed = joinPoint.proceed();
        return  proceed;
    }
}
